#include "HPSocketHttpWrap.h"
#include <cassert>
#include <stdexcept>
#include <cstdio>

#include "HttpRequest.h"
#include "HttpResponse.h"
#include "HttpContext.h"


HttpServerWrap::~HttpServerWrap()
{
}

void HttpServerWrap::Register(HttpMethod method, const std::string& uri, Router::callback_type cb)
{
	auto realUri = toString(method).append(uri);
	if (!m_pRouter->Add(realUri, cb)) {
		throw std::domain_error("插入失败或重复定义!");
	}
}

EnHandleResult HttpServerWrap::OnPrepareListen(ITcpServer* pSender, SOCKET soListen)
{
	return EnHandleResult::HR_OK;
}

EnHandleResult HttpServerWrap::OnAccept(ITcpServer* pSender, CONNID dwConnID, UINT_PTR soClient)
{
	auto* pExtra = new HttpContext(this->m_exceptHandles);
	assert(pExtra);
	if (pExtra) {
		pSender->SetConnectionExtra(dwConnID, pExtra);
		return EnHandleResult::HR_OK;
	}
	return EnHandleResult::HR_ERROR;
}

EnHandleResult HttpServerWrap::OnHandShake(ITcpServer* pSender, CONNID dwConnID)
{
	return EnHandleResult::HR_OK;
}

EnHandleResult HttpServerWrap::OnReceive(ITcpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
	return HR_OK;
}

EnHandleResult HttpServerWrap::OnSend(ITcpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
	return EnHandleResult::HR_OK;
}

EnHandleResult HttpServerWrap::OnClose(ITcpServer* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)
{
	PVOID pExtra = nullptr;
	if (pSender->GetConnectionExtra(dwConnID, &pExtra) && pExtra) {
		std::unique_ptr<HttpContext> agent((HttpContext *)pExtra);
	}
	return EnHandleResult::HR_OK;
}

EnHandleResult HttpServerWrap::OnShutdown(ITcpServer* pSender)
{
	return EnHandleResult::HR_OK;
}

EnHttpParseResult HttpServerWrap::OnMessageBegin(IHttpServer* pSender, CONNID dwConnID)
{
    PVOID pExtra = nullptr;
    if (pSender->GetConnectionExtra(dwConnID, &pExtra) && pExtra) {
        HttpContext *httpContext = (HttpContext *)pExtra;
        assert(httpContext);
        httpContext->m_connId = dwConnID;
        httpContext->httpServer = m_httpServer;
        httpContext->m_request = std::make_unique<HttpRequest>(*httpContext);
        httpContext->m_response = std::make_unique<HttpResponse>(*httpContext);
    }
	return EnHttpParseResult::HPR_OK;
}

EnHttpParseResult HttpServerWrap::OnRequestLine(IHttpServer* pSender, CONNID dwConnID, LPCSTR lpszMethod, LPCSTR lpszUrl)
{

    PVOID pExtra = nullptr;
    if (pSender->GetConnectionExtra(dwConnID, &pExtra) && pExtra) {
        HttpContext *httpContext = (HttpContext *)pExtra;
        assert(httpContext);
        auto realUri = toUpper(lpszMethod).append(lpszUrl);
        Router::callback_type cb;
        if(!m_pRouter->Lookup(realUri, httpContext->callback)){
            httpContext->writeNotFount();
        }
    }

	return EnHttpParseResult::HPR_OK;
}

EnHttpParseResult HttpServerWrap::OnHeader(IHttpServer* pSender, CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue)
{
	return EnHttpParseResult::HPR_OK;
}

EnHttpParseResult HttpServerWrap::OnHeadersComplete(IHttpServer* pSender, CONNID dwConnID)
{
	return EnHttpParseResult::HPR_OK;
}

EnHttpParseResult HttpServerWrap::OnBody(IHttpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
    PVOID pExtra = nullptr;
    if (pSender->GetConnectionExtra(dwConnID, &pExtra) && pExtra) {
        HttpContext *httpContext = (HttpContext *)pExtra;
        assert(httpContext);
        httpContext->wRequestBody(reinterpret_cast<const char *>(pData), iLength);
    }
	return EnHttpParseResult::HPR_OK;
}

EnHttpParseResult HttpServerWrap::OnChunkHeader(IHttpServer* pSender, CONNID dwConnID, int iLength)
{
	return EnHttpParseResult::HPR_OK;
}

EnHttpParseResult HttpServerWrap::OnChunkComplete(IHttpServer* pSender, CONNID dwConnID)
{
	return EnHttpParseResult::HPR_OK;
}

EnHttpParseResult HttpServerWrap::OnMessageComplete(IHttpServer* pSender, CONNID dwConnID)
{
    PVOID pExtra = nullptr;
    if (pSender->GetConnectionExtra(dwConnID, &pExtra) && pExtra) {
        HttpContext *httpContext = (HttpContext *)pExtra;
        assert(httpContext);
        if(!httpContext->handle()){
            httpContext->writeNotFount();
        }
        httpContext->clear();
    }
	return EnHttpParseResult::HPR_OK;
}

EnHttpParseResult HttpServerWrap::OnUpgrade(IHttpServer* pSender, CONNID dwConnID, EnHttpUpgradeType enUpgradeType)
{
	return EnHttpParseResult();
}

EnHttpParseResult HttpServerWrap::OnParseError(IHttpServer* pSender, CONNID dwConnID, int iErrorCode, LPCSTR lpszErrorDesc)
{
	return EnHttpParseResult();
}

EnHandleResult HttpServerWrap::OnWSMessageHeader(IHttpServer* pSender, CONNID dwConnID, BOOL bFinal, BYTE iReserved, BYTE iOperationCode, const BYTE lpszMask[4], ULONGLONG ullBodyLen)
{
	return EnHandleResult();
}

EnHandleResult HttpServerWrap::OnWSMessageBody(IHttpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
	return EnHandleResult();
}

EnHandleResult HttpServerWrap::OnWSMessageComplete(IHttpServer* pSender, CONNID dwConnID)
{
	return EnHandleResult();
}

std::shared_ptr<IHttpServer> HttpServerWrap::GetServer() {
    return m_httpServer;
}
